package com.yanggu.jt808.codec;

import com.yanggu.jt808.consts.Jt808Constant;
import com.yanggu.jt808.model.base.DataPackage;
import com.yanggu.jt808.util.Jt808Util;
import com.yanggu.jt808.util.RespHelper;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.ByteBufUtil;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import io.netty.util.ReferenceCountUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 *  JT808协议编码器,转义规则: 0x7e -> 0x7d 0x02
 * @Description  JT808Encoder1
 * @Author guoyb
 * @Date   2023/11/7 14:45
 */
@Slf4j
@Component
@ChannelHandler.Sharable
public class JT808Encoder1 extends MessageToByteEncoder<DataPackage> {

    @Override
    protected void encode(ChannelHandlerContext ctx, DataPackage msg, ByteBuf out) throws Exception {
        log.debug(msg.toString());
        //将消息转成成byteBuf
        ByteBuf byteBuf = msg.toByteBufMsg();
        //设置校验码
        byteBuf.writeByte(Jt808Util.xorSumBytes(byteBuf));
        //转义待发送的数据
        ByteBuf escape = escape(byteBuf);
        log.info("发送数据>>>>> ip: {}, hex: {}\n", ctx.channel().remoteAddress(), ByteBufUtil.hexDump(escape));
        //发送数据

        out.writeBytes(escape);
        ReferenceCountUtil.safeRelease(msg.getMsgBody());
        ReferenceCountUtil.safeRelease(escape);
    }

    /**
     * 转义待发送数据
     *
     * @param raw
     * @return
     */
    public ByteBuf escape(ByteBuf raw) {
        int len = raw.readableBytes();
        ByteBuf buf = ByteBufAllocator.DEFAULT.directBuffer(len + 12);
        buf.writeByte(Jt808Constant.PKG_DELIMITER);
        while (len > 0) {
            byte b = raw.readByte();
            if (b == 0x7e) {
                buf.writeByte(0x7d);
                buf.writeByte(0x02);
            } else if (b == 0x7d) {
                buf.writeByte(0x7d);
                buf.writeByte(0x01);
            } else {
                buf.writeByte(b);
            }
            len--;
        }
        ReferenceCountUtil.safeRelease(raw);
        buf.writeByte(Jt808Constant.PKG_DELIMITER);
        return buf;
    }

    /**
     * 生成header中的消息体属性
     *
     * @param bodyLen
     * @return
     */
    public static short createDefaultMsgBodyProperty(short bodyLen) {
        return createMsgBodyProperty(bodyLen, (byte) 0, false, (byte) 0);
    }

    public static short createMsgBodyProperty(short bodyLen, byte encType, boolean isSubPackage, byte reversed) {
        int subPkg = isSubPackage ? 1 : 0;
        int ret = (bodyLen & 0x3FF) | ((encType << 10) & 0x1C00) | ((subPkg << 13) & 0x2000)
                | ((reversed << 14) & 0xC000);
        return (short) (ret & 0xffff);
    }

}
